package com.code.family.controller;

import cn.hutool.core.codec.Base64Encoder;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.code.family.config.CustomConfig;
import com.code.family.entity.annotation.CheckPermission;
import com.code.family.entity.annotation.OperationLog;
import com.code.family.entity.dto.LoginUser;
import com.code.family.entity.dto.RegisterUser;
import com.code.family.entity.dto.UserPassword;
import com.code.family.entity.pojo.PageParam;
import com.code.family.entity.pojo.User;
import com.code.family.entity.vo.UserVo;
import com.code.family.service.UserService;
import com.code.family.utils.JwtUtils;
import com.code.family.utils.ResultVo;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpSession;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.output.ByteArrayOutputStream;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.util.DigestUtils;
import org.springframework.web.bind.annotation.*;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Date;
import java.util.Map;
import java.util.Optional;

/**
 * 用户管理
 * @author 上玄
 */
@RestController
@RequestMapping("/api/user")
@Slf4j
@RequiredArgsConstructor
public class UserController {

    private final UserService userService;
    @Resource
    private DefaultKaptcha defaultKaptcha;
    @Resource
    private CustomConfig customConfig;

    /**
     * 获取验证码
     */
    @PostMapping("/captcha")
    public ResultVo imageCode(HttpServletRequest request) {
        log.info("获取验证码");
        //生成的验证码
        String code = defaultKaptcha.createText();
        // 验证码存入session
        HttpSession session = request.getSession();
        session.setAttribute("code", code);
        System.out.println(session.getAttribute("code"));
        // 生成图片,转换为bas64字符串
        BufferedImage bufferedImage = defaultKaptcha.createImage(code);
        ByteArrayOutputStream outputStream = null;
        try {
            outputStream = new ByteArrayOutputStream();
            ImageIO.write(bufferedImage, "jpg", outputStream);
            String base64 = Base64Encoder.encode(outputStream.toByteArray());
            String codeImage = "data:image/jpg;base64," + base64.replaceAll("\r\n", "");
            return ResultVo.success("获取成功",codeImage);
        } catch (IOException e) {
            log.error(e.getMessage());
        } finally {
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    log.error(e.getMessage());
                }
            }
        }

        return ResultVo.success("获取成功",code);
    }


    /**
     * 注册
     */
    @PostMapping("/register")
    public ResultVo register(@RequestBody RegisterUser userDto) {
        //判断用户名是否存在
        if (userService.getOne(new LambdaQueryWrapper<User>().eq(User::getUsername, userDto.getUsername())) != null) {
            return ResultVo.error("用户名已存在");
        }
        //判断邮箱是否存在
        if (userService.getOne(new LambdaQueryWrapper<User>().eq(User::getEmail, userDto.getEmail())) != null) {
            return ResultVo.error("该邮箱已存在");
        }
        //密码hashMD5加密
        userDto.setPassword(DigestUtils.md5DigestAsHex(userDto.getPassword().getBytes()));
        // 把UserDto转换为User对象
        User user = new User();
        BeanUtils.copyProperties(userDto, user);
        // 图片处理
        if (user.getAvatar() != null) {
            // 只存相对路径
            String avatar = user.getAvatar().replaceAll("^.*?/uploads/", "uploads/");
            user.setAvatar(avatar);
            log.info("图片处理：{}", user.getAvatar());
        }
        // 添加创建时间
        user.setCreatedAt(new Date());
        user.setUpdatedAt(new Date());
        //保存用户
        if (userService.save(user)) {
            return ResultVo.success("注册成功");
        }else {
            return ResultVo.error("注册失败");
        }
    }


    /**
     *  登录
     */
//    @OperationLog(description = "用户登录")
    @PostMapping("/login")
    public ResultVo login(@RequestBody LoginUser loginUser, HttpServletRequest request) {
        //获取验证码
        String code = (String) request.getSession().getAttribute("code");
        System.out.println("验证码：" + code);
        if (!StringUtils.equals(loginUser.getCaptcha(), code)) {
            log.error("验证码错误{}:{}", loginUser.getCaptcha(), code);
            return ResultVo.error("验证码错误");
        }
        int role = loginUser.getRole();
        User user = new User();
        user.setUsername(loginUser.getUsername());
        user.setPassword(loginUser.getPassword());
        // 判断用户名是否存在
        User u = userService.getOne(new LambdaQueryWrapper<User>().eq(User::getUsername, user.getUsername()));
        if (u == null) {
            return ResultVo.error("用户不存在");
        }
        if (u.getStatus() == 1) {
            return ResultVo.error("用户已被禁用，请联系管理员解封");
        }
        // 判断权限是否正确
        if (u.getRole() != role){
            return ResultVo.error("权限不正确");
        }
        // 密码hashMD5加密
        user.setPassword(DigestUtils.md5DigestAsHex(user.getPassword().getBytes()));
        // 判断密码是否正确
        if (!u.getPassword().equals(user.getPassword())) {
            return ResultVo.error("密码错误");
        }
        // 返回VO
        UserVo userVo = new UserVo();
        BeanUtils.copyProperties(u, userVo);
        // 修改图片路径
        if (u.getAvatar() != null) {
            userVo.setAvatar(u.getAvatar().replaceAll("uploads/", customConfig.getFullUploadPath()));
        }
        // 设置token
        Map<String, Object> data = Map.of("username", userVo.getUsername(), "id", userVo.getId(), "role", userVo.getRole());
        String token = JwtUtils.generateJwt(data);
        // 设置token
        userVo.setToken(token);
        // 返回结果
        return ResultVo.success("登录成功",userVo);
    }

    /**
     * 修改密码
     * @param user 用户
     */
    @OperationLog(description = "用户修改密码")
    @PostMapping("/changePassword")
    public ResultVo changePassword(@RequestBody UserPassword user) {
        // 判断旧密码是否正确
        user.setPassword(DigestUtils.md5DigestAsHex(user.getPassword().getBytes()));
        User u = userService.getOne(new LambdaQueryWrapper<User>().eq(User::getId, user.getId()));
        if (u == null) {
            return ResultVo.error("用户不存在");
        }
        if (!u.getPassword().equals(user.getPassword())) {
            return ResultVo.error("旧密码错误");
        }
        // 更新密码：对新密码进行MD5加密，并更新到数据库中
        String newPasswordHash = DigestUtils.md5DigestAsHex(user.getNewPassword().getBytes());
        // 设置新密码
        u.setPassword(newPasswordHash);
        log.info("修改密码：{}", u);
        if (userService.updateById(u)) {
            return ResultVo.success("修改成功");
        }else {
            return ResultVo.error("修改失败");
        }
    }

    /**
     * 新增
     */
    @OperationLog(description = "新增用户")
    @CheckPermission
    @PostMapping
    public ResultVo add(@RequestBody User user) {
        // 密码hashMD5加密
        user.setPassword(DigestUtils.md5DigestAsHex(user.getPassword().getBytes()));
        // 图片处理
        if (user.getAvatar() != null) {
            // 只存相对路径
            String avatar = user.getAvatar().replaceAll("^.*?/uploads/", "uploads/");
            user.setAvatar(avatar);
            log.info("图片处理：{}", user.getAvatar());
        }
        if (userService.save(user)) {
            return ResultVo.success("新增成功");
        }else {
            return ResultVo.error("新增失败");
        }
    }

    /**
     * 编辑
     */
    @OperationLog(description = "编辑用户")
    @CheckPermission
    @PutMapping
    public ResultVo edit(@RequestBody User user) {
        if (user.getPassword() != null && user.getPassword().length() != 32){
            // 密码hashMD5加密
            user.setPassword(DigestUtils.md5DigestAsHex(user.getPassword().getBytes()));
        }
        // 更新时间
        user.setUpdatedAt(new Date());
        // 图片处理
        if (user.getAvatar() != null) {
            // 只存相对路径
            String avatar = user.getAvatar().replaceAll("^.*?/uploads/", "uploads/");
            user.setAvatar(avatar);
            log.info("图片处理：{}", user.getAvatar());
        }
        if (userService.updateById(user)) {
            return ResultVo.success("编辑成功");
        }else {
            return ResultVo.error("编辑失败");
        }
    }

    /**
     * 删除
     */
    @OperationLog(description = "删除用户")
    @CheckPermission
    @DeleteMapping("/{userId}")
    public ResultVo delete(@PathVariable Integer userId) {
        if (userService.removeById(userId)) {
            return ResultVo.success("删除成功");
        }else {
            return ResultVo.error("删除失败");
        }
    }

    /**
     * 查询用户列表
     * @param param 分页参数
     * @return 分页数据
     */
    @GetMapping
    public ResultVo getList(PageParam param) {
        // 创建LambdaQueryWrapper
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        // 判断是否为普通用户
        queryWrapper.eq(User::getRole, 0);
        if (StringUtils.isNotEmpty(param.getValue())) {
            queryWrapper.like(User::getName, param.getValue());
        }
        // 创建分页对象
        Page<User> page = new Page<>(Optional.ofNullable(param.getCurrentPage()).orElse(1), param.getPageSize());
        // 执行分页查询
        IPage<User> pageList = userService.page(page, queryWrapper);
        // 返回结果
        return ResultVo.success(pageList);
    }

    /**
     * 查询管理员列表
     */
    @GetMapping("/admin")
    public ResultVo getAdminList(PageParam param) {
        // 创建LambdaQueryWrapper
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getRole, 1);
        if (StringUtils.isNotEmpty(param.getValue())) {
            queryWrapper.like(User::getName, param.getValue());
        }
        // 创建分页对象
        Page<User> page = new Page<>(Optional.ofNullable(param.getCurrentPage()).orElse(1), param.getPageSize());
        // 执行分页查询
        IPage<User> pageList = userService.page(page, queryWrapper);
        // 返回结果
        return ResultVo.success(pageList);
    }

}
